package com.yiwu.netty;

import com.yiwu.common.enums.ResponseCode;
import com.yiwu.common.exception.BusinessException;
import com.yiwu.netty.handler.HeartBeatHandler;
import com.yiwu.netty.handler.WebSocketHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import jakarta.annotation.PreDestroy;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * @version 1.0
 * @description TODO
 * @date 2024/5/28 1:09
 */
@Slf4j
@Component
public class NettyServer implements Runnable {


    @Value("${netty.server.port}")
    private int port;

    private static final EventLoopGroup bossGroup = new NioEventLoopGroup(1);
    private static final EventLoopGroup workerGroup = new NioEventLoopGroup();

    @Resource
    private WebSocketHandler webSocketHandler;

    @PreDestroy
    public void close() {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }

    @Override
    public void run() {
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.DEBUG))
                    .childHandler(new ChannelInitializer<>() {
                        // SocketChannel 是基于TCP/IP进行通信
                        @Override
                        public void initChannel(Channel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            //设置处理器
                            pipeline.addLast(new HttpServerCodec());
                            //设置请求content最大值
                            pipeline.addLast(new HttpObjectAggregator(64 * 1024));
                            //添加心跳机制
                            // 读超时、写超时、所有超时
                            pipeline.addLast(new IdleStateHandler(300, 0, 0, TimeUnit.SECONDS));
                            pipeline.addLast(new HeartBeatHandler());
                            //http 升级ws
                            pipeline.addLast(new WebSocketServerProtocolHandler("/ws", null, true, 64 * 1024, true, true, 10000L));
                            pipeline.addLast(webSocketHandler);

                            pipeline.addLast();
                        }
                    });
//                    .option(ChannelOption.SO_BACKLOG, 128)
//                    .childOption(ChannelOption.SO_KEEPALIVE, true);

            ChannelFuture f = b.bind(port).sync();
            log.info("启动成功，nettyServer.port:{}", port);
            f.channel().closeFuture().sync();
        } catch (Exception e) {
            throw new BusinessException(ResponseCode.WS_ERROR);
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }
}